﻿
using Dapper;
using HBase;
 
using MongoDB.Bson;
using MongoDB.Driver;
using Net.http;
using System;
using System.Collections.Generic;
using System.Data; 
using System.Linq; 

namespace hCommand {
    [Serializable]
    public abstract class GkTransaction : Sw {
        public String name;
        public GkTransaction() {
            name = this.GetType().Name;
        }
 
        protected virtual void initConnection() {
            if(conn == null ) {
                conn = DBUtils.newWMSConn(BaseConfig.prefixal);
            }
            if (conn.State == ConnectionState.Closed) {
                conn.Open();
            }
            tran = conn.BeginTransaction();
        }


        private IDbConnection conn;
        private IDbTransaction tran;

       
        public TransRes doWork() {
            try {
                initConnection();
            } catch (Exception e) {
                if (conn != null) {
                    LoggerCommon.error(InfoCode.error_transaction, "事务开启异常", e);
                    conn.Close(); 

                    conn.Open();
                } 
                return new TransRes("开启事务异常,请重试3次");
            }



            long time = DateTime.Now.Ticks / 10000;
            try {
                TransRes res = Execute();
                if( res.s ) {
                    tran.Commit();
                    log(res.msg, time);
                } else {
                    tran.Rollback();
                    log(res.msg ,time);
                }
                return res;
            } catch( Exception ex ) {
                tran.Rollback();

                LoggerCommon.error(InfoCode.error_transaction,ex.Message ,ex);
                log(ex.Message + ex.StackTrace ,time);
                return new TransRes(ex.Message);
            } finally {
                if(conn.State == ConnectionState.Open ) {
                    conn.Close();
                }
            }
        }
        void log(String error ,long begin) {
            try {
                if( LoggerCommon.loggerMongon ) {
                    long time = DateTime.Now.Ticks / 10000 - begin;
                    IMongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection<GkTransaction>();
                    BsonDocument document = new BsonDocument();
                    document.Add("info" , JsonUtil.toView(this));
                    document.Add("time" ,DateTime.Now);
                    document.Add("error" ,error);
                    document.Add("ip" ,NetConfig.MeIp);
                    document.Add("use" ,( int ) time);
                    document.Add("_id" ,HUtil.to64());
                    collection.InsertOne(document);
                }
            } catch { }
        }
        //protected abstract bool Execute(IDbConnection connection, IDbTransaction transaction);
        /// <summary>
        /// 重写基础类方便，在库存计算入出库wcs任务生成过程中各种业务逻辑判断错误消息返回上层调用方法 by leo.yang 20200723
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="transaction"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        protected abstract TransRes Execute();

        public T getById<T>(long id) where T : class {
            return conn.GetById<T>(id , tran);
        }

        public List<T> query<T>(String sql,object obj=null) {
            return conn.Query<T>(sql, obj, tran).ToList();
        }
        public T  queryUnique<T>(String sql, object obj = null) {
            return conn.QueryUnique<T>(sql, obj, tran);
        }

        public bool updateNotNull<T>(T t) where T : class {
            return conn.updateNotNull(t , tran);
        }
        public bool update<T>(T t) where T : class {
            return conn.Update(t, tran);
        }
        public int batchInsert<T>(List<T> entities) where T : class {
            return conn.BatchInsert(entities, tran);
        }
        public long insert<T>(T t ) where T : class {
            return conn.Insert(t , tran);
        }
        public bool delete(BaseEntity t){
            return conn.delete(t,tran);
        }
        public  int exec(string sql ,object p) {
           return conn.Execute(sql ,p , tran);
        }
    }
}
